﻿using EFDemo.Controllers;
using MiniExcelLibs.Attributes;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace EFDemo
{
    public class ExcelHelper
    {
        public static List<T> ExcelToList<T>(Stream stream) where T : class ,new()
        {
            HSSFWorkbook wb = new HSSFWorkbook(stream);
            ISheet sheet = wb.GetSheetAt(0);
            IRow root = sheet.GetRow(0);
            int columnLength = root.LastCellNum;
            Dictionary<string, int> excelColumn = new Dictionary<string, int>();
            for (int i = 0; i < columnLength; i++)
            {
                string name = root.GetCell(i).StringCellValue;
                excelColumn.Add(name, i);
            }

            List<T> result = new List<T>();
            var aaa = typeof(T).GetProperties();
            for (int i = 1; i <= sheet.LastRowNum; i++)
            {
                IRow row = sheet.GetRow(i);
                T entity = new T();
                foreach (PropertyInfo item in aaa)
                {
                    var bbb = item.GetCustomAttribute<ExcelColumnAttribute>();
                    int index = excelColumn[bbb.Name];

                    var value = row.GetCell(index);
                    if (value.CellType == CellType.Numeric)
                    {
                        if (item.PropertyType == typeof(string))
                        {
                            item.SetValue(entity, value.NumericCellValue.ToString());
                        }
                        else
                        {
                            item.SetValue(entity, value.NumericCellValue);
                        }
                    }
                    else if (value.CellType == CellType.String)
                    {
                        item.SetValue(entity, value.StringCellValue);
                    }
                }
                result.Add(entity);
            }

            return result;
        }

        public static List<TOut> ToMap<TIn, TOut>(List<TIn> list)
        {
            ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
            List<MemberBinding> memberBindingList = new List<MemberBinding>();
            foreach (var item in typeof(TOut).GetProperties())
            {
                MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
                MemberBinding memberBinding = Expression.Bind(item, property);
                memberBindingList.Add(memberBinding);
            }
            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
            Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
            {
                    parameterExpression
            });

            var func=lambda.Compile();

            List<TOut> result= new List<TOut>();
            foreach(TIn item in list)
            {
                result.Add(func(item));
            }
            return result;
        }

    }
}
